//
//  vdRenderer.h
//  Void Dead
//
//  Created by Sidney Just on 20.11.09.
//
//  Copyright © 2009 by Sidney Just
//  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
//  documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
//  the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, 
//  and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//  The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
//  INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
//  PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
//  FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
//  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//

#import <Foundation/Foundation.h>

#import "vdTexNode.h"
#import "vdColor.h"
#import "vdHeader.h"
#import "vdShader.h"
#import "vdShaderLib.h"

@class vdKernel;

/**
 * This class allows you to render objects easily on the screen. Other than the normal render process, the vdRenderer tries to optimize the added Vertices as much as possible.
 * <br> (If the vertices or tex coordinates are the only things that changes, the vdRenderer will render those objects as one object).
 * <br> There will be only one vdRenderer at a time, if you try to [alloc init] the vdRenderer it will return the sharedRenderer pointer! 
 **/

@interface vdRenderer : NSObject <vdShaderProtocol> {
	int objectsIn;
	int objectsOut;
	
	@private
	GLfloat *vertices;
	GLfloat *texCoords;
	
	vdTexNode *texture;
	
	int verticesPerObject; // The vertices per Object
	int availableVertices; // The actual allocated Size for vertices (it's always more than the real vertix count due to minimze the malloc/realloc calls)
	int vertexPos; // The actual Position in the vertexArray
	
	vdColor *color;
	vdShader *shader;
	GLenum mode;
	
	GLenum sBlendFactor;
	GLenum dBlendFactor;
	BOOL   blendEnabled;
	
	vdShader *defaultShader;
	
	float backingWidth;
	float backingHeight;
	
	vdRenderingAPI API;
	
	int lines;
	CGPoint *linesFrom;
	CGPoint *linesTo;
	
	int positionsPerVertex;
	
	GLfloat	matrix[16];
	BOOL		useMatrix;
}

/**
 * The objects that are passed to the vdRenderer
 **/
@property int objectsIn;

/**
 * The objects that the vdRenderer draws on the screen.
 * <br>In the worst case this var is equal to objectsIn, in the best case this is 1!
 **/
@property int objectsOut;

/**
 * Returns the pointer to the sharedRenderer object.
 @return Pointer to the sharedRenderer.
 **/
+ (vdRenderer *)sharedRenderer;

/**
 * Sets the shader for the next objects. If there are objects with another shader queued, then they will be rendered before the new shader will be applied.
 @param _shd Pointer to the shader that should be used or NULL if the default shader (vdShaderDefaul) should be used.
 **/
- (void)setShader:(vdShader *)_shd;

/**
 * Sets the mode for glDrawArrays. If there are objects with another mode queued, then they will be rendered befor the new mode will be applied.
 @param _mode GLenum of the new mode (eg. GL_TRIANGLES, GL_TRIANGLE_FAN etc)
 **/
- (void)setMode:(GLenum)_mode;

/**
 * Sets a new blend mode
 @param enabled YES if GL_BLEND should be enabled or NO if not
 @param sfactor The source blend factor
 @param dfactor The dest blend factor
 **/
- (void)setBlendMode:(BOOL)enabled sFactor:(GLenum)sfactor dFactor:(GLenum)dfactor;

/**
 * Sets the focus on the vdRenderer. Must and will(!) be called evrey frame, so ignore this function.
 **/
- (void)setFocus;

/**
 * This will force the vdRenderer to draw all stored vertices and tex coordinates.
 * <br> Use this only if you want to draw your content without make use of the vdRenderer!
 **/
- (void)flushContent;

/**
 * Draws the scene on the screen and resets some variables. Must and will(!) be called on the end of evrey frame, so ignore this function,
 **/
- (void)finalizeScene;

/**
 * This adds the given Vertices and Texture coordinates to the rendering queue.
 @param _ver Pointer to the Vertices Array that should be drawn
 @param _tex Pointer to the Texture Coordinates Array that is associated with the Vertices
 @param _ppo The positions per vertex (this won't affect the texture coordinates per vertex (2))
 @param _size The size of the Vertices and Texture Coordinates Array (both must have the same size!)
 @param _texNode Pointer to the texture of the object
 @param _col The color of the object
 **/
- (void)addVertices:(GLfloat *)_ver texCoords:(GLfloat *)_tex posPerVertex:(int)_ppo size:(int)_size texture:(vdTexNode *)_texNode color:(vdColor *)_col;

/**
 * This adds the given Vertices and Texture coordinates to the rendering queue.
 @param _ver Pointer to the Vertices Array that should be drawn
 @param _tex Pointer to the Texture Coordinates Array that is associated with the Vertices
 @param _ppo The positions per vertex (this won't affect the texture coordinates per vertex (2))
 @param _size The size of the Vertices and Texture Coordinates Array (both must have the same size!)
 @param _texNode Pointer to the texture of the object
 @param _col The color of the object
 @param _matrix Pointer to an 4x4 (16 units float array) model matrix for the object
 @remark It's expensive to call this function for every object you want to render, use this only if you really need a different model matrix!
 **/
- (void)addVertices:(GLfloat *)_ver texCoords:(GLfloat *)_tex posPerVertex:(int)_ppo size:(int)_size texture:(vdTexNode *)_texNode color:(vdColor *)_col andMatrix:(GLfloat *)_matrix;

@end
